/*
 *  SF3KtoProT - Converts Star Fighter 3000 music to Amiga ProTracker format
 *  Main program and command line arguments parser
 *  Copyright (C) 2009  Chris Bazley
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public Licence as published by
 *  the Free Software Foundation; either version 2 of the Licence, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public Licence for more details.
 *
 *  You should have received a copy of the GNU General Public Licence
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/* ISO library header files */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdbool.h>

/* Local header files */
#include "decomp.h"
#include "samp.h"
#include "protracker.h"
#include "platform.h"
#include "main.h"

#define VERSION_STRING "0.01 [02 Jun 2009]"

static int syntax_msg(FILE *f, const char *path)
{
  assert(f != NULL);
  assert(path != NULL);
  fprintf(f,
          "usage: %s [switches] <music-file> <samples-dir>\n"
          "Switches (names may be abbreviated):\n"
          "  -allowsfx           Allow notes to be played using sound effect samples\n"
          "  -blankend           Append a blank pattern to the end of the song\n"
          "  -channelglissando   Restrict glissando effects to the same channel\n"
          "  -extraoctaves       Utilise non-standard ProTracker octaves 0 and 4\n"
          "  -fastglissando      Fast glissandos (contiguous Tone Portamento commands)\n"
          "  -help               Show version number and usage guide\n"
          "  -indexfile <file>   Index file to use instead of looking in <samples-dir>\n"
          "  -outfile <file>     Specify a name for the output file\n"
          "  -verbose or -debug  Emit debug output\n",
          find_leaf(path));
  return EXIT_FAILURE;
}

static void copyright_msg(FILE *f)
{
  fprintf(f, "Star Fighter 3000 to ProTracker convertor, "VERSION_STRING"\n");
  fprintf(f, "Copyright (C) 2009, Christopher Bazley\n");
}

static bool is_switch(const char *arg, const char *name)
{
  /* Allow any abbreviation of the canonical switch name */
  size_t arg_len = strlen(arg);
  return arg_len <= strlen(name) && strncmp(arg, name, arg_len) == 0;
}

int main(int argc, const char *argv[])
{
  void *music_data;
  SampleInfo *samp_data = NULL;
  unsigned int nsamp, n, flags = 0;
  const char *output_file = NULL, *index_file = NULL;
  char *default_output = NULL, *default_index = NULL;
  bool verbose, success = false;

  assert(argc > 0);
  assert(argv != NULL);

  /* Parse any options specified on the command line */
  for (n = 1; n < argc && argv[n][0] == '-'; n++) {
    const char *opt = argv[n] + 1;

    if (is_switch(opt, "allowsfx")) {
      /* Allow sound effects during music */
      flags |= FLAGS_ALLOW_SFX;
    } else if (is_switch(opt, "blankend")) {
      /* Generate an extra blank pattern to prevent late notes being cut off */
      flags |= FLAGS_BLANK_PATTERN;
    } else if (is_switch(opt, "extraoctaves")) {
      /* Utilise non-standard ProTracker octaves 0 and 4 in preference to
         pre-tuning samples. */
      flags |= FLAGS_EXTRA_OCTAVES;
    } else if (is_switch(opt, "fastglissando")) {
      /* Do 'fast' glissandos (albeit at slowest available ProTracker speed) */
      flags |= FLAGS_GLISSANDO_FAST;
    } else if (is_switch(opt, "help")) {
      /* Output version number and usage information */
      copyright_msg(stdout);
      (void)syntax_msg(stdout, argv[0]);
      return EXIT_SUCCESS;
    } else if (is_switch(opt, "indexfile")) {
      /* Samples index file path was specified */
      if (++n >= argc) {
        fprintf(stderr, "No samples index file name specified\n");
        return syntax_msg(stderr, argv[0]);
      }
      index_file = argv[n];
    } else if (is_switch(opt, "verbose") || is_switch(opt, "debug")) {
      /* Enable debugging output */
      flags |= FLAGS_VERBOSE;
    } else if (is_switch(opt, "outfile")) {
      /* Output file path was specified */
      if (++n >= argc) {
        fprintf(stderr, "No output file name specified\n");
        return syntax_msg(stderr, argv[0]);
      }
      output_file = argv[n];
    } else if (is_switch(opt, "channelglissando")) {
      /* Restrict effect of glissando command to a single channel */
      flags |= FLAGS_GLISSANDO_SINGLE;
    } else {
      fprintf(stderr, "Unrecognised option '%s'\n", opt);
      return syntax_msg(stderr, argv[0]);
    }
  }
  if (argc < n + 2) {
    fprintf(stderr, "Not enough command line arguments\n");
    return syntax_msg(stderr, argv[0]);
  }
  if (argc > n + 2) {
    fprintf(stderr, "Spurious command line arguments\n");
    return syntax_msg(stderr, argv[0]);
  }

  verbose = (flags & FLAGS_VERBOSE) != 0;
  if (verbose)
    copyright_msg(stdout);

  /* Load the Star Fighter 3000 music file */
  music_data = load_compressed(verbose, argv[n]);
  if (music_data == NULL)
    goto exit;

  /* If no samples index filename was specified then invent one */
  if (index_file == NULL) {
    /* Append hard-wired leaf name to generate full path of index file */
    default_index = append_leaf(argv[n + 1], "index");
    if (default_index == NULL) {
      fprintf(stderr,"Failed to allocate memory for samples index file path\n");
      goto exit;
    }
    index_file = default_index;
  }

  /* Load the sound samples index file */
  samp_data = load_sample_index(verbose, index_file, argv[n + 1], &nsamp);
  if (samp_data == NULL)
    goto exit;

  /* If no output filename was specified then invent one */
  if (output_file == NULL) {
    default_output = append_ext(argv[n], "mod");
    if (default_output == NULL) {
      fprintf(stderr,"Failed to allocate memory for output file path\n");
      goto exit;
    }
    output_file = default_output;
  }

  /* Create the ProTracker output file */
  if (!create_protracker(flags,
                         argv[n],
                         music_data,
                         argv[n + 1],
                         samp_data,
                         nsamp,
                         output_file))
    goto exit;

  if (!set_file_type(output_file))
  {
    fprintf(stderr, "Failed to set type of output file '%s'\n", output_file);
    goto exit;
  }

  success = true;

exit:
  free(music_data);
  free(samp_data);
  free(default_output);
  free(default_index);

  if (verbose)
    puts(success ? "Conversion completed successfully" : "Conversion failed");

  return (success ? EXIT_SUCCESS : EXIT_FAILURE);
}
